#!/usr/bin/env python3
"""
MinIO配置和工具类
支持分片上传、断点续传等功能
"""

import os
from minio import Minio
from minio.error import S3Error
from typing import Optional
import logging

logger = logging.getLogger(__name__)

# MinIO配置
MINIO_HOST = os.getenv("MINIO_HOST", "localhost:9000")
MINIO_ACCESS_KEY = os.getenv("MINIO_ACCESS_KEY", "minioadmin")
MINIO_SECRET_KEY = os.getenv("MINIO_SECRET_KEY", "minioadmin")
MINIO_BUCKET = os.getenv("MINIO_BUCKET", "redbook-media")
MINIO_SECURE = os.getenv("MINIO_SECURE", "false").lower() == "true"

class MinIOClient:
    """MinIO客户端封装"""
    
    def __init__(self):
        try:
            self.client = Minio(
                MINIO_HOST,
                access_key=MINIO_ACCESS_KEY,
                secret_key=MINIO_SECRET_KEY,
                secure=MINIO_SECURE
            )
            self.bucket = MINIO_BUCKET
            self._ensure_bucket()
        except Exception as e:
            logger.warning(f"MinIO初始化失败，将使用本地存储: {e}")
            self.client = None
            self.bucket = MINIO_BUCKET
    
    def _ensure_bucket(self):
        """确保bucket存在"""
        try:
            if not self.client.bucket_exists(self.bucket):
                self.client.make_bucket(self.bucket)
                logger.info(f"Bucket '{self.bucket}' 创建成功")
            else:
                logger.info(f"Bucket '{self.bucket}' 已存在")
        except (S3Error, Exception) as e:
            logger.warning(f"MinIO连接失败，将使用本地存储: {e}")
            self.client = None
    
    def upload_file(
        self,
        file_path: str,
        object_name: str,
        content_type: str = "application/octet-stream"
    ) -> str:
        """
        上传文件到MinIO
        
        Args:
            file_path: 本地文件路径
            object_name: MinIO中的对象名称
            content_type: 文件类型
            
        Returns:
            文件的URL
        """
        if not self.client:
            raise Exception("MinIO客户端不可用")
        
        try:
            self.client.fput_object(
                self.bucket,
                object_name,
                file_path,
                content_type=content_type
            )
            
            url = f"http://{MINIO_HOST}/{self.bucket}/{object_name}"
            logger.info(f"文件上传成功: {object_name}")
            return url
            
        except S3Error as e:
            logger.error(f"文件上传失败: {e}")
            raise
    
    def upload_data(
        self,
        data: bytes,
        object_name: str,
        content_type: str = "application/octet-stream"
    ) -> str:
        """
        上传字节数据到MinIO
        
        Args:
            data: 文件数据（字节）
            object_name: MinIO中的对象名称
            content_type: 文件类型
            
        Returns:
            文件的URL
        """
        try:
            from io import BytesIO
            
            self.client.put_object(
                self.bucket,
                object_name,
                BytesIO(data),
                length=len(data),
                content_type=content_type
            )
            
            url = f"http://{MINIO_HOST}/{self.bucket}/{object_name}"
            logger.info(f"数据上传成功: {object_name}")
            return url
            
        except S3Error as e:
            logger.error(f"数据上传失败: {e}")
            raise
    
    def get_presigned_upload_url(self, object_name: str, expires_in: int = 3600) -> str:
        """
        获取预签名上传URL（用于前端直接上传）
        
        Args:
            object_name: MinIO中的对象名称
            expires_in: 过期时间（秒）
            
        Returns:
            预签名URL
        """
        try:
            url = self.client.presigned_put_object(
                self.bucket,
                object_name,
                expires=expires_in
            )
            return url
            
        except S3Error as e:
            logger.error(f"获取预签名URL失败: {e}")
            raise
    
    def delete_file(self, object_name: str) -> bool:
        """
        删除文件
        
        Args:
            object_name: 要删除的对象名称
            
        Returns:
            是否删除成功
        """
        try:
            self.client.remove_object(self.bucket, object_name)
            logger.info(f"文件删除成功: {object_name}")
            return True
            
        except S3Error as e:
            logger.error(f"文件删除失败: {e}")
            return False
    
    def file_exists(self, object_name: str) -> bool:
        """检查文件是否存在"""
        try:
            self.client.stat_object(self.bucket, object_name)
            return True
        except S3Error:
            return False

# 创建全局MinIO客户端实例
try:
    minio_client = MinIOClient()
    logger.info("MinIO客户端初始化成功")
except Exception as e:
    logger.error(f"MinIO客户端初始化失败: {e}")
    minio_client = None
